/**
 * 前端服务管理模块
 */

const { spawn } = require('child_process');
const axios = require('axios');
const path = require('path');
const fs = require('fs');
const logger = require('../utils/logger');
const { isPortInUse } = require('../utils/port');

// 前端进程引用
let frontendProcess = null;
let frontendPort = null;

/**
 * 启动前端服务
 * @param {Object} config - 前端服务配置
 * @returns {Promise<boolean>} 是否启动成功
 */
exports.startFrontend = async (config) => {
  try {
    const { startCommand, startArgs, baseDir } = config.frontend;
    let { port } = config.frontend;
    
    // 构建启动参数
    const args = [...startArgs];
    
    // 如果指定了端口，添加端口参数（Vite格式）
    if (port) {
      frontendPort = port;
      
      // 检查端口是否被占用
      if (await isPortInUse(port)) {
        logger.warn(`端口 ${port} 已被占用，尝试等待服务就绪...`);
        // 检查是否已经有服务在运行
        const isReady = await checkFrontendHealth(config);
        if (isReady) {
          logger.info('前端服务似乎已经在运行');
          return true;
        }
        logger.error(`端口 ${port} 被占用且不是有效的前端服务，请先释放该端口`);
        return false;
      }
      
      // 为Vite添加端口参数
      if (startArgs.includes('dev')) {
        args.push('--port', port.toString());
      }
    }
    
    // 检查package.json是否存在
    const packageJsonPath = path.resolve(baseDir, 'package.json');
    if (!fs.existsSync(packageJsonPath)) {
      logger.error(`前端目录中未找到package.json: ${baseDir}`);
      return false;
    }
    
    logger.info(`启动前端服务，命令: ${startCommand} ${args.join(' ')}`);
    
    // 启动前端进程
    frontendProcess = spawn(startCommand, args, {
      cwd: baseDir,
      stdio: ['ignore', 'pipe', 'pipe'],
      shell: process.platform === 'win32' // Windows平台需要shell
    });
    
    // 处理标准输出，从中提取端口信息
    frontendProcess.stdout.on('data', (data) => {
      const output = data.toString().trim();
      if (output) {
        logger.debug(`[前端输出] ${output}`);
        
        // 尝试从输出中提取端口号
        if (!frontendPort) {
          const portMatch = output.match(/port\s+(\d+)/i) || 
                           output.match(/http:\/\/localhost:(\d+)/);
          if (portMatch && portMatch[1]) {
            frontendPort = parseInt(portMatch[1], 10);
            logger.info(`前端服务正在端口 ${frontendPort} 上运行`);
          }
        }
        
        // 检查启动成功的标志
        if (output.includes('VITE v') || output.includes('ready in')) {
          logger.info('前端服务启动成功！');
        }
      }
    });
    
    // 处理错误输出
    frontendProcess.stderr.on('data', (data) => {
      const output = data.toString().trim();
      if (output) {
        logger.error(`[前端错误] ${output}`);
      }
    });
    
    // 处理进程退出
    frontendProcess.on('exit', (code) => {
      logger.info(`前端服务已退出，退出码: ${code}`);
      frontendProcess = null;
      frontendPort = null;
    });
    
    // 处理进程错误
    frontendProcess.on('error', (err) => {
      logger.error(`启动前端服务失败: ${err.message}`);
      frontendProcess = null;
      frontendPort = null;
    });
    
    // 等待服务就绪
    logger.info('等待前端服务就绪...');
    const isReady = await waitForFrontendReady(config);
    
    if (isReady && frontendPort) {
      logger.info(`前端服务已成功启动，运行在 http://localhost:${frontendPort}`);
      return true;
    } else {
      logger.error('前端服务启动超时或无法确定端口');
      // 尝试停止进程
      await exports.stopFrontend();
      return false;
    }
  } catch (error) {
    logger.error(`启动前端服务时发生错误: ${error.message}`);
    await exports.stopFrontend();
    return false;
  }
};

/**
 * 停止前端服务
 * @returns {Promise<boolean>} 是否停止成功
 */
exports.stopFrontend = async () => {
  try {
    if (!frontendProcess) {
      logger.info('前端服务未运行');
      return true;
    }
    
    logger.info('正在停止前端服务...');
    
    // 在不同平台上安全地终止进程
    if (process.platform === 'win32') {
      // Windows平台
      frontendProcess.kill('SIGTERM');
    } else {
      // Unix-like平台
      frontendProcess.kill('SIGINT');
    }
    
    // 设置超时
    const timeoutPromise = new Promise(resolve => 
      setTimeout(() => resolve(false), 10000)
    );
    
    // 等待进程退出
    const exitPromise = new Promise(resolve => {
      frontendProcess.once('exit', () => {
        frontendProcess = null;
        frontendPort = null;
        resolve(true);
      });
    });
    
    const success = await Promise.race([exitPromise, timeoutPromise]);
    
    if (!success) {
      logger.warn('优雅关闭超时，强制终止前端服务');
      if (frontendProcess) {
        frontendProcess.kill('SIGKILL');
        frontendProcess = null;
        frontendPort = null;
      }
    }
    
    logger.info('前端服务已停止');
    return true;
  } catch (error) {
    logger.error(`停止前端服务时发生错误: ${error.message}`);
    frontendProcess = null;
    frontendPort = null;
    return false;
  }
};

/**
 * 检查前端服务状态
 * @param {Object} config - 前端服务配置
 * @returns {Promise<boolean>} 服务是否正在运行
 */
exports.checkFrontendStatus = async (config) => {
  try {
    // 检查进程是否在运行
    if (frontendProcess && !frontendProcess.killed) {
      // 如果知道端口，检查端口是否被占用
      if (frontendPort) {
        const isPortUsed = await isPortInUse(frontendPort);
        if (isPortUsed) {
          // 检查健康状态
          return await checkFrontendHealth(config);
        }
      }
      return true; // 进程在运行但端口未知
    }
    return false;
  } catch (error) {
    logger.debug(`检查前端服务状态时发生错误: ${error.message}`);
    return false;
  }
};

/**
 * 获取前端服务端口
 * @returns {number|null} 前端服务端口或null
 */
exports.getFrontendPort = () => {
  return frontendPort;
};

/**
 * 检查前端服务健康状态
 * @param {Object} config - 前端服务配置
 * @returns {Promise<boolean>} 服务是否健康
 */
function checkFrontendHealth(config) {
  const port = frontendPort || config.frontend.port;
  if (!port) {
    logger.debug('无法检查前端服务健康状态：端口未知');
    return false;
  }
  
  // 尝试不同的健康检查路径
  const healthPaths = [
    config.frontend.healthCheckPath,  // 配置的路径
    '/',                              // 根路径
    '/index.html'                     // 可能的入口文件
  ];
  
  // 尝试所有可能的健康检查路径
  const tryHealthPath = async (paths) => {
    if (paths.length === 0) {
      logger.debug(`所有健康检查路径都失败，端口 ${port}`);
      return false;
    }
    
    const currentPath = paths[0];
    const currentUrl = `http://localhost:${port}${currentPath}`;
    
    try {
      logger.debug(`尝试前端健康检查: ${currentUrl}`);
      const response = await axios.get(currentUrl, {
        timeout: 3000,
        validateStatus: status => status >= 200 && status < 400
      });
      
      if (response.status >= 200 && response.status < 400) {
        logger.debug(`前端健康检查成功: ${currentUrl}`);
        return true;
      }
    } catch (error) {
      // 对于前端服务，连接错误是正常的，特别是在启动过程中
      logger.debug(`前端健康检查失败 [${currentUrl}]: ${error.message}`);
    }
    
    // 当前路径失败，尝试下一个
    return tryHealthPath(paths.slice(1));
  };
  
  return tryHealthPath(healthPaths);
}

/**
 * 等待前端服务就绪
 * @param {Object} config - 前端服务配置
 * @returns {Promise<boolean>} 服务是否在超时前就绪
 */
function waitForFrontendReady(config) {
  const { healthCheckTimeout } = config.frontend;
  const startTime = Date.now();
  const checkInterval = 1000;
  
  return new Promise((resolve) => {
    const checkHealth = async () => {
      // 检查是否超时
      if (Date.now() - startTime > healthCheckTimeout) {
        resolve(false);
        return;
      }
      
      // 必须知道端口才能检查
      if (frontendPort) {
        // 检查健康状态
        const isHealthy = await checkFrontendHealth(config);
        if (isHealthy) {
          resolve(true);
          return;
        }
      }
      
      // 继续检查
      setTimeout(checkHealth, checkInterval);
    };
    
    // 开始检查
    setTimeout(checkHealth, 3000); // 初始延迟，给前端多一点时间启动
  });
}